mod create_task;
mod custom_json_extractor;
mod get_tasks;
mod hello_world;
mod update_tasks;
mod validate_with_serde;
mod partial_update_task;

use axum::http::HeaderName;
use axum::routing::{post, put};
use axum::{extract::FromRef, routing::get, Router};
use sea_orm::DatabaseConnection;
use std::time::Duration;
use tower::ServiceBuilder;
use tower_http::compression::CompressionLayer;
use tower_http::cors::{Any, CorsLayer};
use tower_http::request_id::{MakeRequestUuid, SetRequestIdLayer};
use tower_http::timeout::TimeoutLayer;
use tower_http::trace::TraceLayer;

use create_task::create_task;
use custom_json_extractor::custom_json_extractor;
use get_tasks::get_all_tasks;
use get_tasks::get_one_task;
use hello_world::hello_world;
use update_tasks::update_task;
use partial_update_task::partial_update_task;
use validate_with_serde::validate_with_serde;

#[derive(Clone, FromRef)]
pub struct AppState {
    pub database: DatabaseConnection,
}
pub async fn create_routes(database: DatabaseConnection) -> Router {
    let app_state = AppState { database };
    let router = Router::new()
        .route("/hello_world", get(hello_world))
        .route("/validate_with_serde", post(validate_with_serde))
        .route("/custom_json_extractor", post(custom_json_extractor))
        .route("/tasks", post(create_task))
        .route("/tasks", get(get_all_tasks))
        .route("/tasks/:id", get(get_one_task))
        .route("/tasks/:id", put(update_task))
        .route("/tasks/:id", post(partial_update_task))
        .layer(
            // 官方推荐在ServiceBuilder上一次性载入
            ServiceBuilder::new()
                .layer(TraceLayer::new_for_http())
                .layer(
                    CompressionLayer::new()
                        .br(true)
                        .deflate(true)
                        .gzip(true)
                        .zstd(true),
                )
                // 超时时间是200ms
                .layer(TimeoutLayer::new(Duration::new(5, 0)))
                // 需要设置一个请求头的键名，一般叫x-request-id
                .layer(SetRequestIdLayer::new(
                    HeaderName::from_static("x-request-id"),
                    MakeRequestUuid,
                ))
                // 默认情况下不放行，所以需要根据自己需求设置必要的允许规则。
                .layer(
                    CorsLayer::new()
                        .allow_methods(axum::http::Method::GET)
                        .allow_origin(Any),
                ),
        )
        // .layer(Extension(AppState{database}))
        .with_state(app_state);

    // .with_state(app_state);
    router
}
